package com.springboot.service.aop;



import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @Author: luobendexiaoqiang
 * @Date: 2020/8/1 16:14
 */
@Component
@Aspect
@Slf4j
//@Order(2)
public class ScheduledHandlerAop {

    /**
     * 正在执行的定时器的缓存
     */
    private static volatile Map<String,String> executeMethods = Maps.newConcurrentMap();

    /**
     * 记录消息队列请求的次数
     */
    private static volatile AtomicInteger requestCount = new AtomicInteger(0);

    /**
     * 添加方法
     * @param methodName
     */
    private void addMethod(String methodName){
        requestCount.incrementAndGet();
        executeMethods.put(methodName,methodName);
    }

    /**
     * 删除方法
     * @param methodName
     */
    private void removeMethod(String methodName){
        requestCount.decrementAndGet();
        executeMethods.remove(methodName);
    }

    /**
     * 判断方法是否在集合中存在
     * @param methodName
     * @return
     */
    private boolean checkIsContains(String methodName){
        return null != executeMethods.get(methodName);
    }

    /**
     *  如果为空，则返回true，否则为false
     * @return
     */
    public static boolean jobIsComplate(){
        return requestCount.get() <= 0;
    }
    /**
     * 要拦截的方法，只针对scanValidEndFinishedOrder，fetchTicketCenterProject方法做测试
     *
     */

    @Pointcut(
            " execution(public * com.springboot..*.*(..)) && @annotation(org.springframework.scheduling.annotation.Scheduled) "
    )
    public void proxyAspect() {

    }

    @Around("proxyAspect()")
    public Object doInvoke(ProceedingJoinPoint joinPoint){

        String methodName = joinPoint.getSignature().toString();
        log.debug(methodName + "=====ScheduledHandlerAop 拦截的定时器的AOP开始===");
        Object obj = null;
        try{

            //如果executeMethods缓存中存在指定的方法，则不能执行，直接结束，等待下次执行
            if (checkIsContains(methodName)){
                log.info("ScheduledHandlerAop 上次的任务还没有执行完成，放弃此次执行的方法 ：" + methodName);
                return obj;
            }
            log.info("定时任务开始被拦截order2");
            //如果executeMethods缓存中不存在指定的方法，则将此方法添加到缓存中，并执行此定时器，
            addMethod(methodName);
            obj =  joinPoint.proceed();
            log.info("定时任务结束被拦截order2");
            //定时器执行完，清除缓存中的执行完的定时器的标记
            removeMethod(methodName);

        }catch (Throwable e){
            log.error("ScheduledHandlerAop 拦截的定时器的方法执行失败",e);
            log.error("ScheduledHandlerAop 拦截的定时器的方法执行失败,失败的定时器",methodName);
            //任务执行异常，清除缓存中的执行完的定时器的标记
            removeMethod(methodName);
        }

        log.debug(methodName + "=====ScheduledHandlerAop 拦截的定时器的AOP结束===");
        return  obj;
    }
}

